package online.chazi.netkit;

import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.SimpleChannelInboundHandler;
import io.netty.handler.timeout.IdleState;
import io.netty.handler.timeout.IdleStateEvent;
import lombok.extern.slf4j.Slf4j;
import online.chazi.netkit.channel.NetkitChannelEvent;
import online.chazi.netkit.channel.NetkitFutureListener;
import online.chazi.netkit.listener.NetkitChanelListener;
import online.chazi.netkit.messaging.Message;

/**
 * 说明：作者很懒，什么都没留下
 * Created by 叉子同学 on 2020-04-23 18:59
 */
@Slf4j
public class NetkitHandler extends SimpleChannelInboundHandler<Message> {

    private NetkitContext context;
    private Session session;
    private NetkitChanelListener chanelListener;

    public NetkitHandler(NetkitContext context) {
        this.context = context;
        this.chanelListener = context.getChanelListener();
    }

    @Override
    public void userEventTriggered(ChannelHandlerContext ctx, Object evt) throws Exception {
        if (evt instanceof IdleStateEvent) {
            IdleStateEvent event = (IdleStateEvent) evt;
            if ((event.state().equals(context.getSessionIdleState())
                    || IdleState.ALL_IDLE.equals(context.getSessionIdleState()))) {
                log.debug("The session {} was timeout, close this channel - [{}]", session.getSessionId(), session.getRemoteAddress());
                session.close();
            }
        }
    }

    @Override
    public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception {
        chanelListener.onExceptionCaught(new NetkitChannelEvent(this.context, ctx.channel()), cause);
        super.exceptionCaught(ctx, cause);
    }

    @Override
    public void channelUnregistered(ChannelHandlerContext ctx) throws Exception {
        super.channelUnregistered(ctx);
        chanelListener.onUnregistered(new NetkitChannelEvent(this.context, ctx.channel()));
    }

    @Override
    public void channelRegistered(ChannelHandlerContext ctx) throws Exception {
        log.debug("channelRegistered..");
        if (context.getSessionSize() > context.getMaxConnections()) {
            Message message = new Message(0);
            this.session.sendMessage(message).addFutureListener(new NetkitFutureListener() {
                public void onComplete(boolean success, Session session) {
                    session.close();
                }
            });
            log.warn("[WARNING]:The server connections has reached maximum.");
        } else {
            chanelListener.onRegistered(new NetkitChannelEvent(this.context, ctx.channel()));
            session = context.createSession(ctx.channel());
            super.channelRegistered(ctx);
        }
    }

    protected void channelRead0(ChannelHandlerContext ctx, Message message) throws Exception {
        log.debug("channelRead0..");
        chanelListener.onMessageReceived(new NetkitChannelEvent(this.context, ctx.channel()), message);
        session.onMessageReceived(message);
    }

}
